﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wedo.Recognition.Domain.Models;
using Wedo.Utility.Export;
using Wedo.Recognition.Domain;
using Wedo.Utility.ExportFile;
using System.IO;
using System.Reflection;
using Wedo.Recognition.Service;
using Wedo.Utility;
using System.Xml;

namespace Wedo.Recognition.Service.BankImport
{
    //public class BankDataExport : BaseCSVExport<BankData>
    //{
    //    public BankDataExport()
    //    {
    //        types = Wedo.Utility.Reflection.EnumHelper<BDReceiveType, int>.GetByDict(); 
    //    }
    //    private Dictionary<int, string> types;

    //    protected override string[] GetNames()
    //    {
    //        string[] heades = { "账单编号", "收款类型", "收款人或票据号", "币种", "实际收款", "银行手续费", "银行备注", "交易附言", "交易附言2" };
    //        return heades;
    //    }

    //    protected override string[] GetValues(BankData item)
    //    {
    //        string type = types[item.ReceiveType < 1 ? 1 : item.ReceiveType] ?? "";
    //        string paidIn=item.BankPaidIn.GetValueOrDefault(0).ToString();
    //        string fee = item.BankServiceFee.GetValueOrDefault(0).ToString();
    //        string[] vals = { item.Assiginment, type, item.Payer, item.Currency, paidIn, fee, item.BankRemarkNum, item.LCNumber, item.TradeAddionalComment };
    //        return vals;
    //    }
    //}

    public class  BankDataExport : BaseExportCsv<BankData>
    {
        public BankDataExport(string filePath, List<BankData> datasource)
            : base(filePath, datasource, "BankData")
        {
        }


        public Dictionary<string, string> BankNames { get; set; }

        protected override Dictionary<string, string> ParseModel(BankData model)
        {
            var dict = base.ParseModel(model);
            dict["BankCode"] = GetBankName(model.BankCode);
            return dict;
        }

        private string GetBankName(string bankCode)
        {
            if (!BankNames.ContainsKey(bankCode))
            {
                return bankCode??"";
            }
            return BankNames[bankCode];
        }
    }

 

    public class BaseExportCsv<T> where T : class
    {
        protected string _expertPath;
        protected string _Split;
        protected Encoding EncodeType { get; set; }
        protected IEnumerable<T> _dataSource;

        public string Split { get { return Split; } }
        public string ExpertPath { get { return _expertPath; } }

        /// <summary>
        /// 头
        /// </summary>
        private IEnumerable<string> headers;

        private Dictionary<string, string> mapping;

        /// <summary>
        /// 导出路径，导出数据，导出配置
        /// </summary>
        /// <param name="expertPath"></param>
        /// <param name="dataSource"></param>
        /// <param name="type"></param>
        public BaseExportCsv(string expertPath, IEnumerable<T> dataSource, string type)
        {
             mapping = ExportMapConfig.GetInstance().ExportMaps[type];

            _Split = "\t";
            headers = mapping.Keys;
            _expertPath = expertPath;
            EncodeType = Encoding.Unicode;
            _dataSource = dataSource;
        }

        protected virtual string FormatFileContent(string str)
        {
            str = str.Replace("\r", "").Replace("\n", "");
            if (str.Contains(_Split) || str.Contains("\""))
            {
                str = str.Replace("\"", "\"\"");
                str = "\"" + str + "\"";
            }
            return str;
        }

        public void  Export()
        {
            Init();
            using (StreamWriter sw = new StreamWriter(_expertPath, false, EncodeType))
            {
                Write(sw, mapping);
                foreach (var m in _dataSource)
                {
                    Write(sw, ParseModel(m));
                }
                sw.Close();
            }
        }

        protected void Write(StreamWriter sw, Dictionary<string, string> vals)
        {
            List<string> list = new List<string>();
            foreach (var item in headers)
            {
                string val = null;
                if (vals.ContainsKey(item))
                {
                    val = vals[item] ;
                }
                list.Add(val ?? "");
            }
            sw.Write(string.Join(_Split,list)+  "\r\n" );
        }
       
        protected void Init()
        {
            string path = Path.GetDirectoryName(_expertPath);
            if (Directory.Exists(path)==false)
            {
                Directory.CreateDirectory(path);
            }

            if (File.Exists(_expertPath))
            {
                File.Delete(_expertPath);
            }
        }

        protected virtual Dictionary<string, string> ParseModel(T model)
        {
            Type t = model.GetType();
            Dictionary<string, string> dict = new Dictionary<string, string>();

            foreach (var item in headers)
            {
                var p= t.GetProperty(item, BindingFlags.Public | BindingFlags.Instance);
                string val =ParseProperty( p.GetValue(model, null));
                dict.Add(item, val);
             }
            return dict;
        }

        protected virtual string ParseProperty(object obj)
        {
            if (obj == null)
                return "";
            else {
                return FormatFileContent(obj.ToString());
            }
        }
    }

    public class ExportMapConfig
    {
        #region 单例
        private static readonly ExportMapConfig instance = new ExportMapConfig();

        private ExportMapConfig()
        {
        }

        public static ExportMapConfig GetInstance()
        {
            return instance;
        }
        #endregion

        private Dictionary<string, Dictionary<string, string>> _ExportMaps;
        public Dictionary<string, Dictionary<string, string>> ExportMaps
        {

            get
            {
                if (_ExportMaps == null)
                {
                    _ExportMaps = new Dictionary<string, Dictionary<string, string>>();
                    XmlDocument doc = new XmlDocument();
                    doc.Load(AppDomain.CurrentDomain.BaseDirectory + "/ExportMap.xml");

                    foreach (XmlNode node in doc.DocumentElement.ChildNodes)
                    {
                        _ExportMaps[node.Name] = new Dictionary<string, string>();
                        foreach (XmlNode field in node.ChildNodes)
                        {
                             _ExportMaps[node.Name][field.Attributes["Name"].Value] = field.Attributes["Text"].Value;
                        }
                    }
                }
                return _ExportMaps;
            }
        }

    }

    public class PaymentApplyExpert : BaseExportCsv<PaymentApply>
    {
        public PaymentApplyExpert(string filePath, List<PaymentApply> datasource)
            : base(filePath, datasource, "PaymentApply")
        {
            types = Wedo.Utility.Reflection.EnumHelper<ApprovalStatus, int>.GetByDict();
        }
        private Dictionary<int, string> types;

        public Dictionary<string, string> UserNames { get; set; }

        protected override Dictionary<string, string> ParseModel(PaymentApply model)
        {
            var dict = base.ParseModel(model);
            dict["Status"]= GetStatusStr(model.Status);
            dict["ReleaseOrder"] = GetUserName(model.ReleaseOrder);

            dict["Approver"] = GetUserName(model.Approver);
            dict["ApplyMan"] = GetUserName(model.ApplyMan);
 
            return dict;
        }
        private string GetUserName(string ad)
        {
            if (UserNames != null)
            {
                if (UserNames.ContainsKey(ad))
                {
                    return UserNames[ad];
                }
            }
            return "";
        }

        private string GetStatusStr(int state)
        {
            if (!types.ContainsKey(state))
            {
                return "";
            }
            return types[state];
        } 
     }
}
